#include <QCoreApplication>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QFile>
#include <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJSValue>
#include <QJsonArray>
#include <QUrlQuery>
#include <QDomDocument>
#include <QDomElement>
#include <QDomNodeList>
#include <QDomAttr>
#include "BaiduTranslate.h"
#include "global.h"


BaiduTranslate::BaiduTranslate()
{

    manager = networkManagerInstance();
    // loadMainPage(); // 如果开机自动启动，请求会在Wifi连接成功之前发送
    QFile scriptFile(":/baidu.js");
    scriptFile.open(QIODevice::ReadOnly);
    baidujs = scriptFile.readAll();
}

QString BaiduTranslate::getUrl(QString url_str)
{
    QUrl url(url_str);
    QNetworkRequest req(url);
    req.setHeader(QNetworkRequest::UserAgentHeader, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) "
                                                    "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36");
    QNetworkReply *reply = manager->get(req);
    connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
    connect(reply, &QNetworkReply::errorOccurred, &loop, &QEventLoop::quit);
    loop.exec();
    if (reply->error() != QNetworkReply::NoError)
    {
        qWarning() << reply->errorString();
    }
    QString res = QString::fromUtf8(reply->readAll());
    reply->deleteLater();
    return res;
}

QByteArray BaiduTranslate::getUrlRawContent(QString url_str)
{
    QUrl url(url_str);
    QNetworkRequest req(url);
    req.setHeader(QNetworkRequest::UserAgentHeader, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) "
                                                    "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36");
    QNetworkReply *reply = manager->get(req);
    connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
    connect(reply, &QNetworkReply::errorOccurred, &loop, &QEventLoop::quit);
    loop.exec();
    if (reply->error() != QNetworkReply::NoError)
    {
        qWarning() << reply->errorString();
    }
    QByteArray res = reply->readAll();
    reply->deleteLater();
    return res;
}

void BaiduTranslate::loadMainPage()
{
    QString res;
    res = getUrl("https://fanyi.baidu.com/");
    res = getUrl("https://fanyi.baidu.com/");
    QRegExp regToken("token: '(.*)'");
    QRegExp regGtk("window.gtk = '(.*)'");
    regToken.setMinimal(true);
    regGtk.setMinimal(true);

    if (regToken.indexIn(res) != -1 && regGtk.indexIn(res) != -1)
    {
        token = regToken.cap(1);
        gtk = regGtk.cap(1);
    }
    else
    {
        qWarning() << "无法获取token gtk";
    }
}

QString BaiduTranslate::langDetect(QString query)
{
    QUrlQuery data;
    data.addQueryItem("query", query);

    QNetworkRequest req(QUrl("https://fanyi.baidu.com/langdetect"));
    req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
    req.setHeader(QNetworkRequest::UserAgentHeader, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) "
                                                    "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36");

    QNetworkReply *reply = manager->post(req, data.toString(QUrl::FullyEncoded).replace("+", "%2B").toUtf8());
    connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
    connect(reply, &QNetworkReply::errorOccurred, &loop, &QEventLoop::quit);
    loop.exec();
    QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
    QJsonObject obj = doc.object();
    if (obj["error"].toInt() == 0)
    {
        return obj["lan"].toString();
    }
    reply->deleteLater();
    return QString();
}

QString BaiduTranslate::getSign(QString query)
{
    myEngine.globalObject().setProperty("__query", query);
    myEngine.globalObject().setProperty("__gtk", gtk);
    QJSValue result = myEngine.evaluate(baidujs);
    return result.toString();
}

QJsonObject BaiduTranslate::dictionary(QString query, QString dst, QString src)
{
    QUrl url("https://fanyi.baidu.com/v2transapi");
    if (src.isEmpty())
        src = langDetect(query);
    QUrlQuery data;
    data.addQueryItem("from", src);
    data.addQueryItem("to", dst);
    data.addQueryItem("query", query);
    data.addQueryItem("simple_means_flag", "3");
    QString sign = getSign(query);
    data.addQueryItem("sign", sign);
    data.addQueryItem("token", token);

    qDebug() << "sign" << sign;

    QNetworkRequest req(QUrl("https://fanyi.baidu.com/v2transapi"));
    req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
    req.setHeader(QNetworkRequest::UserAgentHeader, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) "
                                                    "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36");

    QNetworkReply *reply = manager->post(req, data.toString(QUrl::FullyEncoded).replace("+", "%2B").toUtf8());
    connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
    connect(reply, &QNetworkReply::errorOccurred, &loop, &QEventLoop::quit);

    loop.exec();

    QJsonDocument doc;
    QJsonObject obj;

    if (reply->error() != QNetworkReply::NoError)
    {
        qWarning() << reply->errorString();
        obj["error"] = reply->errorString();
    }
    else
    {
        doc = QJsonDocument::fromJson(reply->readAll());
        obj = doc.object();
        if (obj.contains("error") || obj.contains("errno"))
        {
            qInfo() << obj;
            qWarning() << "Text: baidu sdk error";
        }
    }

    reply->deleteLater();
    return obj;

}

QString BaiduTranslate::TranslateText(QString text)
{
    // 加载token
    if (token.isEmpty() || gtk.isEmpty())
        loadMainPage();

    // 判断是否为英语
    bool is_latin = true;
    for (const auto &c : text)
    {
        if (c.unicode() > 127)
            is_latin = false;
    }
    QJsonObject obj;
    if (is_latin)
        obj = dictionary(text, "zh", "en");
    else
        obj = dictionary(text, "zh", langDetect(text));

    if (obj.contains("dict_result"))
    {
        obj = obj["dict_result"].toObject()["simple_means"].toObject();
        QJsonDocument doc;
        doc.setObject(obj);
        return doc.toJson(QJsonDocument::Compact);
    }
    else if (obj.contains("trans_result"))
    {
       auto data_list = obj["trans_result"].toObject()["data"].toArray();
       QString res;
       for (const auto item : data_list)
       {
           res += item.toObject()["dst"].toString() + "<br/>";
       }
       return res;
    }
    else if (obj.contains("error"))
    {
        return obj["error"].toString();
    }
    else if (obj.empty())
    {
        return QString("empty");
    }
    qInfo() << obj;

    // 998错误则意味需要重新加载主页获取新的token
    if (obj.contains("errno") && obj["errno"].toInt() == 998)
    {
        loadMainPage();
        qInfo() << "loadMainPage";
    }
    return QString("error");
}

